import {
  Cartesian3,
  HeightReference,
  Viewer,
  Math as CesiumMath,
  createWorldTerrainAsync,
  CameraEventType,
  GeoJsonDataSource,
  KeyboardEventModifier,
  Color,
  SunLight,
  SkyAtmosphere,
  JulianDate,
  SceneMode,
  Cartesian2,
  defined,
  ScreenSpaceEventType,
  Cartographic,
  ScreenSpaceEventHandler,
} from 'cesium';
import proj4 from 'proj4';
import {
  addTDT_GOV_Layer,
  CESIUM_KE_HU_IMG_LAYER,
  CESIUM_MAPBOX_IMG_LAYER,
  CESIUM_TDT_CTA_LAYER,
  CESIUM_TDT_CVA_LAYER,
  CESIUM_TDT_IMG_LAYER,
  CESIUM_TDT_TER_LAYER,
  CESIUM_TDT_VEC_LAYER,
} from './map-cesium-layer';

// * 保存地图实例
let map, imageryLayers, imageryLayers_;

let entityListAll = [];
let entityList = [];

/**
 * cesium图层索引
 */
export const cesiumLayerZIndex = {
  影像图层: 1,
  矢量图层: 1,
  mapbox图层: 1,
  '0.8m遥感影像': 1,
  地形晕染图层: 1,
  矢量标记图层: 2,
  影像标记图层: 2,
  地形晕染标记图层: 2,
};

/**
 * 地图初始化
 * @returns {Viewer}
 */
export async function cesiumMapInit(ID) {
  // RequestScheduler.maximumRequestsPerServer = 18; // 设置cesium请求调度器的最大并发数量
  // RequestScheduler.throttleRequests = false; // 关闭请求调度器的请求节流
  map = new Viewer(ID, {
    // https://community.cesium.com/t/how-to-disable-the-error-of-access-token-when-run-offline/12449
    // 如何禁用离线运行时的访问令牌错误?
    // imageryProvider: new TileMapServiceImageryProvider({
    //   url: buildModuleUrl('Assets/Textures/NaturalEarthII'),
    // }),
    homeButton: false, // 主页视角按钮
    animation: false, // 关闭左下角动画组件
    baseLayerPicker: false, // 关闭底图图层切换组件
    geocoder: false, // 关闭搜索定位
    timeline: false, // 时间线部件
    navigationHelpButton: false, // 关闭右上角导航帮助按钮
    navigationInstructionsInitiallyVisible: false, // 不显示提示
    infoBox: false, // 关闭信息框
    selectionIndicator: true, // 关闭选中指示器
    sceneModePicker: false, // 关闭二三维切换
    scene3DOnly: true, // 只渲染 3D，节省资源
    skyAtmosphere: false, // 关闭大气
    shadows: true, // 开启阴影
    shouldAnimate: true, // 开启动画
    fullscreenButton: false, // 全屏按钮
    // requestRenderMode: true, // ✅ 启用请求渲染模式
    // maximumRenderTimeChange: Infinity, // ✅ 降低 CPU 占用
  });

  // MapLookLoopCamera();

  const terrainProvider = await createWorldTerrainAsync({
    requestWaterMask: true,
    requestVertexNormals: true,
  });

  // 叠加地形服务

  // const terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl('http://192.168.2.26:8080/helanshan/', {
  //   requestWaterMask: true,
  //   requestVertexNormals: true,
  //   ellipsoid: Ellipsoid.WGS84,
  //   // heightmapTerrainQuality: 2,
  // });

  map.terrainProvider = terrainProvider;

  // * 调整鼠标习惯
  map.scene.screenSpaceCameraController.zoomEventTypes = [CameraEventType.WHEEL, CameraEventType.PINCH];
  map.scene.screenSpaceCameraController.tiltEventTypes = [
    CameraEventType.PINCH,
    CameraEventType.RIGHT_DRAG,
    {
      eventType: CameraEventType.RIGHT_DRAG,
      modifier: KeyboardEventModifier.CTRL,
    },
  ];
  // 开启深度检测
  map.scene.globe.depthTestAgainstTerrain = true;
  // 设置球体背景色
  map.scene.globe.baseColor = new Color(0, 0, 0, 0);

  // 设置最大最小缩放限制
  map.scene.screenSpaceCameraController.maximumZoomDistance = 20000000;
  // 地形夸大
  map.scene.verticalExaggeration = 1.2;

  // 隐藏品牌标识
  document.getElementsByClassName('cesium-widget-credits')[0].style.display = 'none';
  // 抗锯齿
  map.scene.postProcessStages.fxaa.enabled = true;
  // map.scene.globe.enableLighting = true; //关闭光照
  map.shadows = false; //关闭阴影
  map.scene.light = new SunLight(); // 添加太阳光源
  map.scene.skyAtmosphere = new SkyAtmosphere();
  map.clockViewModel.currentTime = JulianDate.fromDate(new Date('2023-10-01T12:00:00'));
  map.scene.sun.show = false; //还可以viewer.scene.sun.destroy();
  map.scene.moon.show = false;

  // 添加4490解析
  GeoJsonDataSource.crsNames['urn:ogc:def:crs:EPSG::4490'] = (coordinates) => {
    const fromProjection = `GEOGCS["China Geodetic Coordinate System 2000",DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","1043"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]`;

    const toProjection = `GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]`;

    const x = coordinates[0];
    const y = coordinates[1];

    const newCoordinates = proj4(fromProjection, toProjection, [x, y]);

    return Cartesian3.fromDegrees(newCoordinates[0], newCoordinates[1], 0);
  };

  // imageryLayers = addTDT_GOV_Layer(map);

  ChangeBaseLayer('0.8m遥感影像');

  addDistanceLegend(map);

  addMouseCoordinateDisplay(map);

  window.viewer = map;

  map.camera.moveEnd.addEventListener(() => {
    console.info(getCameraState(), 6);
  });

  map.scene.renderError.addEventListener((error) => {
    console.error('Render error:', error);
    // 尝试恢复
    setTimeout(() => map.resize(), 200);
  });

  return map;
}

/**
 * 底图切换
 */
export function ChangeBaseLayer(layerName) {
  imageryLayers && map.imageryLayers.remove(imageryLayers);
  imageryLayers_ && map.imageryLayers.remove(imageryLayers_);

  switch (layerName) {
    case '底图':
      imageryLayers = addTDT_GOV_Layer(map);
      break;

    case '影像图':
      imageryLayers = map.imageryLayers.addImageryProvider(CESIUM_TDT_IMG_LAYER, cesiumLayerZIndex['影像图层']);
      imageryLayers_ = map.imageryLayers.addImageryProvider(CESIUM_TDT_CVA_LAYER, cesiumLayerZIndex['影像图层']);
      break;

    case '道路图':
      imageryLayers = map.imageryLayers.addImageryProvider(CESIUM_TDT_VEC_LAYER, cesiumLayerZIndex['影像图层']);
      imageryLayers_ = map.imageryLayers.addImageryProvider(CESIUM_TDT_CVA_LAYER, cesiumLayerZIndex['矢量标记图层']);
      break;

    case '地形晕染图':
      imageryLayers = map.imageryLayers.addImageryProvider(CESIUM_TDT_TER_LAYER, cesiumLayerZIndex['地形晕染图层']);
      imageryLayers_ = map.imageryLayers.addImageryProvider(
        CESIUM_TDT_CTA_LAYER,
        cesiumLayerZIndex['地形晕染标记图层'],
      );
      break;

    case 'MapBox底图':
      imageryLayers = map.imageryLayers.addImageryProvider(CESIUM_MAPBOX_IMG_LAYER, cesiumLayerZIndex['影像图层']);
      break;

    case '0.8m遥感影像':
      imageryLayers = map.imageryLayers.addImageryProvider(CESIUM_KE_HU_IMG_LAYER, cesiumLayerZIndex['0.8m遥感影像']);
      imageryLayers_ = addTDT_GOV_Layer(map);

      break;
  }
}

/**
 * 返回3d地图实例0
 * @export
 * @returns {Map}
 */
export function getCesiumMap() {
  return map;
}

// 获取当前相机状态
export function getCameraState() {
  const camera = map.camera;

  return {
    destination: {
      x: camera.position.x,
      y: camera.position.y,
      z: camera.position.z,
    },
    heading: camera.heading,
    pitch: camera.pitch,
    roll: camera.roll,
    duration: 2, // 可以根据需要设置
  };
}

/**
 * 二三位切换
 */
export function switch3D2D(viewType) {
  let scene = map.scene;

  switch (viewType) {
    case '三维视图':
      scene.morphTo3D(0);
      viewType = '二维视图';
      break;

    case '二维视图':
      scene.morphTo2D(0);
      viewType = '三维视图';
      break;

    default:
      break;
  }

  // 切换完成后更新实体
  setTimeout(() => {
    updateEntitiesForViewMode();
  }, 10);
}

// 视图切换后更新实体的 heightReference
export function updateEntitiesForViewMode() {
  const is2D = map.scene.mode === SceneMode.SCENE2D;

  entityList?.length &&
    entityList.forEach((entity) => {
      if (entity.billboard) {
        entity.billboard.heightReference = is2D
          ? HeightReference.NONE // 2D 不支持 CLAMP_TO_GROUND
          : HeightReference.CLAMP_TO_GROUND;
      }

      if (entity.label) {
        entity.label.heightReference = is2D ? HeightReference.NONE : HeightReference.CLAMP_TO_GROUND;
      }
    });

  entityListAll?.length &&
    entityListAll.forEach((entity) => {
      if (entity.billboard) {
        entity.billboard.heightReference = is2D
          ? HeightReference.NONE // 2D 不支持 CLAMP_TO_GROUND
          : HeightReference.RELATIVE_TO_TERRAIN;
      }

      if (entity.label) {
        entity.label.heightReference = is2D ? HeightReference.NONE : HeightReference.RELATIVE_TO_TERRAIN;
      }
    });
}

/**
 * 地图控件（放大缩小）
 */
export function zoomMap(direction) {
  const camera = map.camera;

  const position = camera.positionWC.clone();
  const directionVector = camera.directionWC.clone();
  const height = map.scene.globe.ellipsoid.cartesianToCartographic(position).height;

  // 根据相机高度调整缩放的比例
  // const scale = Math.ceil(height / 1000.0);
  // console.log(scale,'scale');
  // let dire = scale>1?scale*direction * 100:direction * 100
  // console.log(dire,'dire');
  const scale = Math.ceil(height / 1.0);
  let dire = scale * direction;

  // 方向矢量与缩放量的乘积
  const zoomVector = Cartesian3.multiplyByScalar(directionVector, dire, new Cartesian3());

  // 新位置为当前位置加上缩放后的矢量
  const newPosition = Cartesian3.add(position, zoomVector, new Cartesian3());
  const heading = camera.heading;
  const pitch = camera.pitch;

  camera.flyTo({
    destination: newPosition,
    orientation: {
      heading: heading,
      pitch: pitch,
    },
    duration: 0.5, // 调整飞行动画的持续时间
  });
}

/**
 * 添加距离图例到地图
 * @param {Viewer} viewer Cesium viewer实例
 */
export function addDistanceLegend(viewer) {
  // 创建DOM元素
  const legendContainerBox = document.createElement('div');

  legendContainerBox.classList.add('distance-legend-c');

  const legendContainer = document.createElement('div');

  legendContainer.classList.add('distance-legend-container-c');
  legendContainerBox.appendChild(legendContainer);

  viewer.container.appendChild(legendContainerBox);

  // 更新比例尺函数
  const updateLegend = () => {
    const scene = viewer.scene;
    const canvas = scene.canvas;

    // 计算屏幕底部中心点对应的世界坐标
    const center = new Cartesian2(canvas.width / 2, canvas.height);
    const ray = viewer.camera.getPickRay(center);
    const position = scene.globe.pick(ray, scene);

    if (!defined(position)) return;

    // 获取100像素对应的世界距离
    const endPoint = new Cartesian2(center.x + 100, center.y);
    const endRay = viewer.camera.getPickRay(endPoint);
    const endPosition = scene.globe.pick(endRay, scene);

    if (!defined(endPosition)) return;

    // 计算两点间地面距离（米）
    const distance = Cartesian3.distance(position, endPosition);

    legendContainer.innerHTML = `1:${Math.round(distance)}m`;
  };

  // 初始更新
  updateLegend();
  // 监听相机变化（包括滚轮缩放）
  viewer.camera.changed.addEventListener(updateLegend);

  return {
    destroy: () => {
      viewer.camera.changed.removeEventListener(updateLegend);
      viewer.container.removeChild(legendContainerBox);
    },
  };
}

/**
 * 添加鼠标坐标显示到地图
 * @param {Viewer} viewer Cesium viewer实例
 */
export function addMouseCoordinateDisplay(viewer) {
  // 创建坐标显示容器
  const coordContainer = document.createElement('div');

  coordContainer.classList.add('mouse-coordinate-container');

  viewer.container.appendChild(coordContainer);

  // 鼠标移动事件处理
  const handler = new ScreenSpaceEventHandler(viewer.scene.canvas);

  handler.setInputAction((movement) => {
    const cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);

    if (cartesian) {
      const cartographic = Cartographic.fromCartesian(cartesian);
      const longitude = CesiumMath.toDegrees(cartographic.longitude).toFixed(6);
      const latitude = CesiumMath.toDegrees(cartographic.latitude).toFixed(6);

      coordContainer.innerHTML = `经度: ${longitude}° 纬度: ${latitude}°`;
    } else {
      coordContainer.innerHTML = '经度: -- 纬度: --';
    }
  }, ScreenSpaceEventType.MOUSE_MOVE);

  return {
    destroy: () => {
      handler.destroy();
      coordContainer.remove();
    },
  };
}
